/*
 * Copyright(C) 2021. Huawei Technologies Co.,Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include "./inc/gesture_detectv2.h"
#include <cstddef>
#include <iostream>
#include "eigen3/Eigen/Core"
#include "eigen3/Eigen/Dense"
#include <cmath>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/types_c.h"
#include "opencv2/core/hal/interface.h"
#include "opencv2/core/types.hpp"
#include "opencv2/imgcodecs.hpp"
#include <opencv2/core/eigen.hpp>
#include "MxBase/E2eInfer/Model/Model.h"
#include "MxBase/E2eInfer/Tensor/Tensor.h"
using namespace std;
using namespace MxBase;
using namespace cv;

constexpr float Con0_1 = 0.1;
constexpr float Con0_5 = 0.5;
constexpr float Con0_8 = 0.8;
constexpr float Con0_9 = 0.9;
constexpr float Con0_9_5 = 0.95;
constexpr float Con0_0_5 = 0.05;
constexpr float Con3_0 = 3.0;
constexpr int Con2 = 2;
constexpr int Con3 = 3;
constexpr int Con4 = 4;
constexpr int Con5 = 5;
constexpr int Con6 = 6;
constexpr int Con7 = 7;
constexpr int Con8 = 8;
constexpr int Con9 = 9;
constexpr int Con10 = 10;
constexpr int Con11 = 11;
constexpr int Con12 = 12;
constexpr int Con13 = 13;
constexpr int Con14 = 14;
constexpr int Con15 = 15;
constexpr int Con16 = 16;
constexpr int Con19 = 19;
constexpr int Con33 = 33;
constexpr int Con64 = 64;
constexpr int Con121 = 121;
constexpr int Con128 = 128;
constexpr int Con255 = 255;
constexpr int Con256 = 256;
int gLastGes = -1;

int gLimbSeq[13][2] = { { 2, 3 }, { 2, 6 }, { 3, 4 }, { 4, 5 }, { 6, 7 }, { 7, 8 }, { 2, 9 }, { 9, 10 }, { 10, 11 }, { 2, 12 },
{ 12, 13 }, { 13, 14 }, { 2, 1 } };

int gMapIdx[19][2] = { { 31, 32 }, { 39, 40 }, { 33, 34 }, { 35, 36 }, { 41, 42 }, { 43, 44 }, { 19, 20 }, { 21, 22 }, { 23, 24 },
{ 25, 26 }, { 27, 28 }, { 29, 30 }, { 47, 48 } };
std::shared_ptr<EngineTransNewT> gMotionDataOld = std::make_shared<EngineTransNewT>();

GestureDetectV2::GestureDetectV2() {}

GestureDetectV2 ::~GestureDetectV2() {}

int find_index(std::vector<int>::iterator begin, std::vector<int>::iterator end, int element) {
    auto temp = begin;
    while (temp != end) {
        if (*temp == element) {
            return element;
        }
        temp += 1;
    }
    return -1;
}

// Custom collation rules
bool cmp2(connectionT a, connectionT b) {
    return a.score>b.score;
}

APP_ERROR op1(float* newResult_1, std::vector <std::vector<keyPointsT>> &allKeyPoints) {
    cv::Mat tempMat;
    Eigen::Matrix <float, Con128, Con128> resizedMatrix;
    Eigen::MatrixXd::Index maxRowF, maxColF;
    Eigen::MatrixXd::Index maxRowNew, maxColNew;
    Eigen::MatrixXd::Index tempMaxRow, tempMaxCol;
    Eigen::MatrixXf gLeftMatrix(Con16, Con16);
    Eigen::MatrixXf gRightMatrix(Con16, Con16);
    Eigen::MatrixXf gTopMatrix(Con16, Con16);
    Eigen::MatrixXf gBottomMatrix(Con16, Con16);
    std::vector <float> onePicPeaks;
    std::vector <keyPointsT> onePicKeyPoints;
    int allPeakIndex = 0;
    float tempA = 0.0;
    bool ifValid = true;
    // Find 14 key points (the first 14 points are enough for the action recognition sequence)
    for (int picNum = 0; picNum < Con14; picNum++) {
        float *v = newResult_1+picNum*Con256;
        // Map to Matrix by column
        Eigen::Map<Eigen::MatrixXf> matrQQ(v, Con16, Con16);
        Eigen::Matrix <float, Con16, Con16> m = matrQQ;
        tempA = m.maxCoeff(&maxRowF, &maxColF);
        // If the maximum value is not greater than 0.1, this frame is considered invalid
        if (tempA < Con0_1) {
            ifValid = false;
            break;
        }

        // Gets the matrix for the left shift of the matrix
        gLeftMatrix.leftCols(Con15) = m.rightCols(Con15);
        gLeftMatrix.col(Con15) = Eigen::MatrixXf::Zero(Con16, 1);
        // Moves to the right
        gRightMatrix.rightCols(Con15) = m.leftCols(Con15);
        gRightMatrix.col(0) = Eigen::MatrixXf::Zero(Con16, 1);
        // Move up
        gTopMatrix.topRows(Con15) = m.bottomRows(Con15);
        gTopMatrix.row(Con15) = Eigen::MatrixXf::Zero(1, Con16);
        // Move down
        gBottomMatrix.bottomRows(Con15) = m.topRows(Con15);
        gBottomMatrix.row(0) = Eigen::MatrixXf::Zero(1, Con16);

        gLeftMatrix = m - gLeftMatrix;
        gRightMatrix = m - gRightMatrix;
        gTopMatrix = m - gTopMatrix;
        gBottomMatrix = m - gBottomMatrix;

        for (int aa = 0; aa < Con16; aa++) {
            for (int bb = 0; bb < Con16; bb++) {
                if (gLeftMatrix(aa, bb) > 0 && gRightMatrix(aa, bb) > 0 && gBottomMatrix(aa, bb) > 0 && gTopMatrix(aa, bb) > 0 && m(aa, bb) > Con0_1) {
                    onePicPeaks.push_back(aa);
                    onePicPeaks.push_back(bb);
                }
            }
        }
        
        // Extend 16x16 to 128x128 size
        cv::eigen2cv(m, tempMat);
        cv::resize(tempMat, tempMat, cv::Size(Con128, Con128), cv::INTER_CUBIC);
        cv::GaussianBlur(tempMat, tempMat, cv::Size(Con3, Con3), Con5);
        cv::cv2eigen(tempMat, resizedMatrix);

        // The local maximum value of each 128x128 image was found according to the local maximum value found in the 16x16 image
        for (int aa = 0; aa < onePicPeaks.size(); aa += Con2) {
            tempMaxRow = onePicPeaks[aa] * Con8 - Con6;
            tempMaxCol = onePicPeaks[aa+1] * Con8 - Con6;
            if (tempMaxRow < 0) {
                tempMaxRow = 0;
            }
            if (tempMaxCol < 0) {
                tempMaxCol = 0;
            }
            if (tempMaxRow > Con121) {
                tempMaxRow = Con121;
            }
            if (tempMaxCol > Con121) {
                tempMaxCol = Con121;
            }

            // Take a 12x12 submatrix and find the maximum value
            Eigen::MatrixXf smallMatrix = resizedMatrix.block<Con12, Con12>(tempMaxRow, tempMaxCol);
            tempA = smallMatrix.maxCoeff(&maxRowNew, &maxColNew);
            // The maximum in a submatrix is considered a local maximum (a key point)
            keyPointsT temp = {float(tempMaxRow + maxRowNew), float(tempMaxCol + maxColNew), allPeakIndex};
            allPeakIndex++;
            onePicKeyPoints.push_back(temp);
        }
        
        // If you don't find a point in one part of the body, the body is missing a key point, and you don't need to go on looking
        if (onePicKeyPoints.size() == 0) {
            return APP_ERR_ACL_FAILURE;
        }
        // The calculated keypoints for each graph are stored in a vector, which then stores the total keypoints
        allKeyPoints.push_back(onePicKeyPoints);
        onePicPeaks.clear();
        onePicKeyPoints.clear();
    }

    if (!ifValid) {
        cout << "invalid image!!" << endl;
        return APP_ERR_ACL_FAILURE;
    }

    return APP_ERR_OK;
}

APP_ERROR op2(float* newResult_0, std::vector <std::vector<keyPointsT>> &allKeyPoints, std::vector <std::vector<connectionT>> &connectionAll) {
    Eigen::Matrix <float, Con128, Con128> scoreMid_0;
    Eigen::Matrix <float, Con128, Con128> scoreMid_1;
    cv::Mat tempMat_0;
    cv::Mat tempMat_1;
    std::vector <connectionT> connectionCandidate;
    // Traverse mapIdx
    for (int kk = 0; kk < Con13; kk++) {
        float *v = newResult_0 + (gMapIdx[kk][0] - Con19)*Con256;
        // Map to Matrix by column
        Eigen::Map<Eigen::MatrixXf> matrQQ_0(v, Con16, Con16);

        Eigen::Map<Eigen::MatrixXf> matrQQ_1(v + Con256, Con16, Con16);

        Eigen::Matrix <float, Con16, Con16> m_0 = matrQQ_0; // score_mid
        Eigen::Matrix <float, Con16, Con16> m_1 = matrQQ_1; // score_mid

        cv::eigen2cv(m_0, tempMat_0);
        cv::eigen2cv(m_1, tempMat_1);
        cv::resize(tempMat_0, tempMat_0, cv::Size(Con128, Con128), cv::INTER_CUBIC);
        cv::resize(tempMat_1, tempMat_1, cv::Size(Con128, Con128), cv::INTER_CUBIC);
        cv::GaussianBlur(tempMat_0, tempMat_0, cv::Size(Con3, Con3), Con3);
        cv::GaussianBlur(tempMat_1, tempMat_1, cv::Size(Con3, Con3), Con3);
        cv::cv2eigen(tempMat_0, scoreMid_0); // score_mid

        cv::cv2eigen(tempMat_1, scoreMid_1); // score_mid

        std::vector <keyPointsT> temp_A = allKeyPoints[gLimbSeq[kk][0] -1];

        std::vector <keyPointsT> temp_B = allKeyPoints[gLimbSeq[kk][1] -1];

        int LA = temp_A.size();
        int LB = temp_B.size();
        if (LA != 0 && LB != 0) {
            // Find the possibility of a connection between each point in La and the key points in LB
            for (int aa = 0; aa < LA; aa++) {
                for (int bb = 0; bb < LB; bb++) {
                    float vec[2] = {temp_B[bb].point_x - temp_A[aa].point_x, temp_B[bb].point_y - temp_A[aa].point_y};
                    float norms = sqrt(vec[0]*vec[0] + vec[1]*vec[1]);
                    if (norms == 0) {
                        continue;
                    }

                    vec[0] /= norms;
                    vec[1] /= norms;
                    Eigen::Matrix <float, Con10, Con2> startEnd;
                    startEnd.col(0) = Eigen::ArrayXf::LinSpaced(Con10, temp_A[aa].point_x, temp_B[bb].point_x);
                    startEnd.col(1) = Eigen::ArrayXf::LinSpaced(Con10, temp_A[aa].point_y, temp_B[bb].point_y);

                    Eigen::Matrix <float, Con10, 1> vec_x;
                    Eigen::Matrix <float, Con10, 1> vec_y;

                    vec_x << scoreMid_0(int(round(startEnd(0, 0))), int(round(startEnd(0, 1)))), scoreMid_0(int(round(startEnd(1, 0))), int(round(startEnd(1, 1)))), scoreMid_0(int(round(startEnd(Con2, 0))), int(round(startEnd(Con2, 1)))), scoreMid_0(int(round(startEnd(Con3, 0))), int(round(startEnd(Con3, 1)))), scoreMid_0(int(round(startEnd(Con4, 0))), int(round(startEnd(Con4, 1)))), scoreMid_0(int(round(startEnd(Con5, 0))), int(round(startEnd(Con5, 1)))), scoreMid_0(int(round(startEnd(Con6, 0))), int(round(startEnd(Con6, 1)))), scoreMid_0(int(round(startEnd(Con7, 0))), int(round(startEnd(Con7, 1)))), scoreMid_0(int(round(startEnd(Con8, 0))), int(round(startEnd(Con8, 1)))), scoreMid_0(int(round(startEnd(Con9, 0))), int(round(startEnd(Con9, 1))));

                    vec_y << scoreMid_1(int(round(startEnd(0, 0))), int(round(startEnd(0, 1)))), scoreMid_1(int(round(startEnd(1, 0))), int(round(startEnd(1, 1)))), scoreMid_1(int(round(startEnd(Con2, 0))), int(round(startEnd(Con2, 1)))), scoreMid_1(int(round(startEnd(Con3, 0))), int(round(startEnd(Con3, 1)))), scoreMid_1(int(round(startEnd(Con4, 0))), int(round(startEnd(Con4, 1)))), scoreMid_1(int(round(startEnd(Con5, 0))), int(round(startEnd(Con5, 1)))), scoreMid_1(int(round(startEnd(Con6, 0))), int(round(startEnd(Con6, 1)))), scoreMid_1(int(round(startEnd(Con7, 0))), int(round(startEnd(Con7, 1)))), scoreMid_1(int(round(startEnd(Con8, 0))), int(round(startEnd(Con8, 1)))), scoreMid_1(int(round(startEnd(Con9, 0))), int(round(startEnd(Con9, 1))));

                    Eigen::Matrix <float, Con10, 1>scoreMidpts = vec_x * vec[0] + vec_y * vec[1];

                    float scoreWithDistPrior = scoreMidpts.sum() / (10.001) + min(64 / (norms - 1 + 1e-3), 0.0);
                    if (scoreWithDistPrior > 0) {
                        int badNum = 0;
                        for (int fff = 0; fff < Con10; fff++) {
                            if (scoreMidpts(fff) < Con0_0_5) {
                                badNum++;
                            }
                        }
                        if (badNum < Con2) {
                            connectionT tempConnection {aa, bb, scoreWithDistPrior};
                            connectionCandidate.push_back(tempConnection);
                        }
                    }
                }
            }
            
            // If there is a set of key points that cannot be connected to each other, it is considered invalid
            if (connectionCandidate.size() == 0) {
                return APP_ERR_ACL_FAILURE;
            }
            // In order of likelihood of connection, from most to least
            sort(connectionCandidate.begin(), connectionCandidate.end(), cmp2);
            std::vector<int> temp_1;
            std::vector<int> temp_2;
            temp_1.push_back(Con33);
            temp_2.push_back(Con33);

            int p_i = 0;
            int p_j = 0;
            // Get all non-repeating connections 获取所有非重复连接
            std::vector<connectionT> oneConnection;
            for (int tt = 0; tt < connectionCandidate.size(); tt++) {
                int i = connectionCandidate[tt].point_1;
                int j = connectionCandidate[tt].point_2;
                
                p_i = find_index(temp_1.begin(), temp_1.end(), i);

                p_j = find_index(temp_2.begin(), temp_2.end(), j);
                if (p_i != i && p_j != j) {
                    temp_1.push_back(i);
                    temp_2.push_back(j);
                    connectionT temp {temp_A[i].num, temp_B[j].num};
                    oneConnection.push_back(temp);
                    if (oneConnection.size() >= min(LA, LB)) {
                        break;
                    }
                }
            }
            connectionCandidate.clear();
            connectionAll.push_back(oneConnection);
            oneConnection.clear();
        }
    }

    return APP_ERR_OK;
}

// Process the results of the output
APP_ERROR GestureDetectV2::Postprocess(Image& image, std::vector<Tensor>& modelOutput, std::shared_ptr<EngineTransNewT> motionDataNew, int &successNum) {
    std::vector <std::vector<keyPointsT>> allKeyPoints;
    float* newResult_1 = (float *)modelOutput[1].GetData();
    op1(newResult_1, allKeyPoints);
    // =======================================================================
    // ===============Look for relationships between key points===============
    // =======================================================================
    // Gets the first output data
    std::vector <std::vector<connectionT>> connectionAll;
    float* newResult_0 = (float *)modelOutput[0].GetData();
    op2(newResult_0, allKeyPoints, connectionAll);
    // =======================================================================
    // ==============Get the full key point of the middle person==============
    // =======================================================================
    int midIndex = -1;
    int minDis = 200;
    int tempIndex[14] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
    float gTempKeyPoints[Con2][Con14];
    // Generates an all-white graph that you can use to draw the resulting graph
    cv::Mat out1(cv::Size(Con128, Con128), CV_8UC3, cv::Scalar(Con255, Con255, Con255));
    // Find the key point of the middle person
    int keySize_0 = allKeyPoints[0].size();
    if (keySize_0 == 0) {
        cout << "have an error" << ".";
    }

    for (int aa = 0; aa < connectionAll[0].size(); aa++) {
        int thisPointX = allKeyPoints[1][connectionAll[0][aa].point_1 % keySize_0].point_x;
        if (abs(thisPointX - Con64) < minDis) {
            minDis = abs(thisPointX - Con64);
            midIndex = aa;
        }
    }

    // the key points 1 and 2 of the middle person
    tempIndex[1] = connectionAll[0][midIndex].point_1;
    tempIndex[Con2] = connectionAll[0][midIndex].point_2;
    // 0 is the connection between 1 and 2, which we found up there, so we start with 1
    for (int aa = 1; aa < Con13; aa++) {
        int index_A = gLimbSeq[aa][0] - 1;
        int index_B = gLimbSeq[aa][1] - 1;
        if (tempIndex[index_A] == -1) {
            return APP_ERR_ACL_FAILURE;
        }

        for (int bb = 0; bb < connectionAll[aa].size(); bb++) {
            if (connectionAll[aa][bb].point_1 == tempIndex[index_A]) {
                tempIndex[index_B] = connectionAll[aa][bb].point_2;
            }
        }
        // If one connection point is not found, the image is deemed invalid and returned directly
        if (tempIndex[index_B] == -1) {
            return APP_ERR_ACL_FAILURE;
        }
    }

    // The 14 key points for the most middle person found are saved in temp_key_points
    for (int aa = 0; aa < Con14; aa++) {
        gTempKeyPoints[0][aa] = allKeyPoints[aa][tempIndex[aa]].point_x;
        gTempKeyPoints[1][aa] = allKeyPoints[aa][tempIndex[aa]].point_y;
        cv::Point p(gTempKeyPoints[0][aa], gTempKeyPoints[1][aa]);
        cv::circle(out1, p, 1, cv::Scalar(0, 0, 0), -1);
        for (int bb = aa + 1; bb < Con14; bb++) {
            tempIndex[bb] -= allKeyPoints[aa].size();
        }
    }

    cv::Point x0(gTempKeyPoints[0][0], gTempKeyPoints[1][0]);
    cv::Point x1(gTempKeyPoints[0][1], gTempKeyPoints[1][1]);
    cv::Point x2(gTempKeyPoints[0][Con2], gTempKeyPoints[1][Con2]);
    cv::Point x3(gTempKeyPoints[0][Con3], gTempKeyPoints[1][Con3]);
    cv::Point x4(gTempKeyPoints[0][Con4], gTempKeyPoints[1][Con4]);
    cv::Point x5(gTempKeyPoints[0][Con5], gTempKeyPoints[1][Con5]);
    cv::Point x6(gTempKeyPoints[0][Con6], gTempKeyPoints[1][Con6]);
    cv::Point x7(gTempKeyPoints[0][Con7], gTempKeyPoints[1][Con7]);
    cv::Point x8(gTempKeyPoints[0][Con8], gTempKeyPoints[1][Con8]);
    cv::Point x9(gTempKeyPoints[0][Con9], gTempKeyPoints[1][Con9]);
    cv::Point x10(gTempKeyPoints[0][Con10], gTempKeyPoints[1][Con10]);
    cv::Point x11(gTempKeyPoints[0][Con11], gTempKeyPoints[1][Con11]);
    cv::Point x12(gTempKeyPoints[0][Con12], gTempKeyPoints[1][Con12]);
    cv::Point x13(gTempKeyPoints[0][Con13], gTempKeyPoints[1][Con13]);
    cv::line(out1, x0, x1, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x1, x2, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x2, x3, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x3, x4, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x1, x5, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x5, x6, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x6, x7, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x1, x8, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x8, x9, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x9, x10, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x1, x11, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x11, x12, cv::Scalar(Con255, 0, 0), 1);
    cv::line(out1, x12, x13, cv::Scalar(Con255, 0, 0), 1);

    cv::imwrite("../result.jpg", out1);

    memcpy(motionDataNew->data[0][0][FRAME_LENGTH-1], gTempKeyPoints[0], sizeof(float)*Con14);
    memcpy(motionDataNew->data[0][1][FRAME_LENGTH-1], gTempKeyPoints[1], sizeof(float)*Con14);
    // x
    memcpy(motionDataNew->data[0][0][0], gMotionDataOld->data[0][0][1], sizeof(float)*Con14*(FRAME_LENGTH - 1));
    // y
    memcpy(motionDataNew->data[0][1][0], gMotionDataOld->data[0][1][1], sizeof(float)*Con14*(FRAME_LENGTH - 1));
    memcpy(gMotionDataOld->data, motionDataNew->data, sizeof(float)*Con2*FRAME_LENGTH*Con14);

    // Find the coordinates of the center points and center them
    float skeletonCenter[Con2][FRAME_LENGTH] = {0.0};
    for (int c = 0; c < Con2; c++) {
        for (int t = 0; t < FRAME_LENGTH; t++) {
            skeletonCenter[c][t] = float((motionDataNew->data[0][c][t][1] + motionDataNew->data[0][c][t][Con8] + motionDataNew->data[0][c][t][Con11]) / float(Con3_0));
            for (int v = 0; v < Con14; v++) {
                motionDataNew->data[0][c][t][v] = motionDataNew->data[0][c][t][v] - skeletonCenter[c][t];
            }
        }
    }

    successNum++;
    return APP_ERR_OK;
}

// PostGestureProcess
APP_ERROR GestureDetectV2::PostGestureProcess(std::vector<Tensor>& modelOutput) {
    float* newResult = static_cast<float *>(modelOutput[0].GetData());
    int maxPosition = max_element(newResult, newResult+Con5) - newResult;
    float down = 1.4;
    float resultTotal = pow(down, newResult[0]) + pow(down, newResult[1]) + pow(down, newResult[Con2]) + pow(down, newResult[Con3]) + pow(down, newResult[Con4]);
    newResult[0] = pow(down, newResult[0]) / resultTotal;
    newResult[1] = pow(down, newResult[1]) / resultTotal;
    newResult[Con2] = pow(down, newResult[Con2]) / resultTotal;
    newResult[Con3] = pow(down, newResult[Con3]) / resultTotal;
    newResult[Con4] = pow(down, newResult[Con4]) / resultTotal;

    bool ifNeedPub = false;
    if (newResult[maxPosition] >= Con0_5) {
        switch (maxPosition) {
            case 0:
                if (newResult[maxPosition] > Con0_9) {
                    if (gLastGes != 0) {
                        cout << " 鼓掌 " << newResult[0] << endl;
                        cout << " 挥手 " << newResult[1] << endl;
                        cout << " 站立 " << newResult[Con2] << endl;
                        cout << " 双手平举 " << newResult[Con3] << endl;
                        cout << " 踢腿 " << newResult[Con4] << endl;
                        cout << "=============================鼓掌" << endl;
                        ifNeedPub = false;
                        gLastGes = Con10;
                    }
                }
                break;
            case 1:
                if (newResult[maxPosition] > Con0_8) {
                    if (gLastGes != 1) {
                        cout << " 鼓掌 " << newResult[0] << endl;
                        cout << " 挥手 " << newResult[1] << endl;
                        cout << " 站立 " << newResult[Con2] << endl;
                        cout << " 双手平举 " << newResult[Con3] << endl;
                        cout << " 踢腿 " << newResult[Con4] << endl;
                        cout << "=============================挥手" << endl;
                        ifNeedPub = false;
                        gLastGes = Con11;
                    }
                }
                break;
            case Con2:
                if (newResult[maxPosition] > Con0_5) {
                    if (gLastGes != Con2) {
                        cout << " 鼓掌 " << newResult[0] << endl;
                        cout << " 挥手 " << newResult[1] << endl;
                        cout << " 站立 " << newResult[Con2] << endl;
                        cout << " 双手平举 " << newResult[Con3] << endl;
                        cout << " 踢腿 " << newResult[Con4] << endl;
                        cout << "=============================站立" << endl;
                        ifNeedPub = false;
                        gLastGes = Con12;
                    }
                }
                break;
            case Con3:
                if (newResult[maxPosition] > Con0_9_5) {
                    if (gLastGes != Con3) {
                        cout << " 鼓掌 " << newResult[0] << endl;
                        cout << " 挥手 " << newResult[1] << endl;
                        cout << " 站立 " << newResult[Con2] << endl;
                        cout << " 双手平举 " << newResult[Con3] << endl;
                        cout << " 踢腿 " << newResult[Con4] << endl;
                        cout << "=============================双手平举" << endl;
                        ifNeedPub = false;
                        gLastGes = Con13;
                    }
                }
                break;
            case Con4:
                if (newResult[maxPosition] > Con0_9) {
                    if (gLastGes != Con4) {
                        cout << " 鼓掌 " << newResult[0] << endl;
                        cout << " 挥手 " << newResult[1] << endl;
                        cout << " 站立 " << newResult[Con2] << endl;
                        cout << " 双手平举 " << newResult[Con3] << endl;
                        cout << " 踢腿 " << newResult[Con4] << endl;
                        cout << "==============================踢腿" << endl;
                        ifNeedPub = false;
                        gLastGes = Con14;
                    }
                }
                break;
            default:
                cout << "max element==nothing  " << maxPosition << "     " << newResult[maxPosition] << endl;
                break;
        }
    }
    return APP_ERR_OK;
}